/**
 * Implementacion de la clase NodeValidator
 */

#include "nodeValidator.hpp"
//#include "../list/list.hpp"
#include "../list/listIterator.hpp"
#include "../main/node.hpp"
#include <stdlib.h>

using namespace std;

NodeValidator::NodeValidator(std::string &fileToParse, std::string &fileConf, Logger *log, int numberOfFields,
							 Graph *graph)
{
	this->parser.create(fileToParse,fileConf,log);
	this->logger = log;
	this->numberOfFieldsExpected = numberOfFields;
	this->graph = graph;
	this->node.setSuccessStatus(4);
}

void NodeValidator::create(std::string &fileToParse, std::string &fileConf, Logger *log, int numberOfFields,
							Graph *graph)
{
	this->parser.create(fileToParse,fileConf,log);
	this->logger = log;
	this->numberOfFieldsExpected = numberOfFields;
	this->graph = graph;
	this->node.setSuccessStatus(4);
}

NodeValidator::~NodeValidator()
{
	this->logger = 0;
	this->numberOfFieldsExpected = 0;
}

void NodeValidator::validate()
{
	std::string field;
	int lineCount 	= 1;
	int fieldAmount = 0;

	while(this->parser.nextLine())
	{
		fieldAmount = this->parser.getNumberOfFields();
		this->validateNumberOfFields(lineCount,fieldAmount);

		for(int fieldNumber = 1; fieldNumber <= fieldAmount; fieldNumber++)
		{
			this->parser.getField(fieldNumber,field);
			this->validateField(lineCount,fieldNumber,field);
			field.clear();
		}
		this->validateGraphElementAdding(lineCount);
		lineCount++;
	}
}

void NodeValidator::validateNumberOfFields(int lineCount, int fieldAmount)
{
	if(fieldAmount != this->numberOfFieldsExpected)
	{
		this->node.setFailStatus(4);
		std::string detail = "Cantidad de campos distinta a la esperada";
		this->logger->reportErrorMessage("NodeValidator","validateNumberOfFields", detail, lineCount);
	}
	else
		this->node.setSuccessStatus(4);
}
void NodeValidator::validateField(int lineCount, int fieldNumber, std::string field)
{
	std::string detail;
	if(fieldNumber == 1)
	{
		if((std::string::npos == field.find_first_of(','))&&(std::string::npos == field.find_first_of('.'))
			&&(field[0] != '0')&&(atoi(field.c_str()) == 0))
		{
			this->node.setNodeId(field);
		}
		else
		{
			std::string detail = "Esperado un literal, se encontro un real";
			this->logger->reportErrorMessage("NodeValidator","validateField", detail,lineCount,fieldNumber);
			this->node.setFailStatus(fieldNumber);
		}
	}
	else
	{
		float numero = atof(field.c_str());
		if((numero > 0)||(numero < 0))
		{
			if(fieldNumber == 2)
				this->node.setPositionX(numero);
			else
				this->node.setPositionY(numero);
		}
		else if (numero == 0)
		{
			std::string detail = "Esperado un real, se encontro un literal, o el real vale cero";
			this->logger->reportWarningMessage("NodeValidator","validateField", detail,lineCount,fieldNumber);
			this->node.setFailStatus(fieldNumber);
		}
	}
}
void NodeValidator::validateGraphElementAdding(int lineCount)
{
	bool success = true;
	std::string detail;

	if(this->node.getPositionXStatus() == 0)
		success = false;
	if(this->node.getPositionYStatus() == 0)
		success = false;
	if(this->node.getNodeIdStatus() == 0)
		success = false;
	if(this->node.getNumberOfFieldsStatus() == 0)
		success = false;

	if(success)
	{
		Node *nodeTemp = this->graph->getNode(this->node.getNodeId());
		if(nodeTemp == NULL)
		{
			Node *newNode = new Node(this->node.getNodeId(),this->node.getPositionX(),this->node.getPositionY());
			bool samePosition = false;

			List<Node> *lista = this->graph->getNodes();
			ListIterator<Node> it = lista->iterator();
			while((it.hasNext())&&(!samePosition))
			{
				if((it.next())->hasSamePosition(newNode))
					samePosition = true;
			}

			if(!samePosition)
			{
				this->graph->addNode(newNode);
				detail = "Nodo agregado, id: "; detail += this->node.getNodeId();
				this->logger->reportSuccessMessage("NodeValidator","validateGraphElementAdding",detail);
			}
			else
			{
				detail = "Nodo con mismas posiciones existente, nuevo nodo descartado, id: ";
				detail += this->node.getNodeId();
				this->logger->reportErrorMessage("NodeValidator","validateGraphElementAdding",detail,lineCount);
			}
		}
		else
		{
			detail = "Nodo con Id existente descartado, id: "; detail += this->node.getNodeId();
			this->logger->reportErrorMessage("NodeValidator","validateGraphElementAdding",detail,lineCount);
		}

	}
	else
	{
		detail = "Nodo descartado";
		this->logger->reportErrorMessage("NodeValidator","validateGraphElementAdding",detail);
		this->node.clear();
	}

}

